#include "KSockAddress.h"
#include "KDebug.h"

KIAddress::~KIAddress()
{
}

KHostAddress::KHostAddress(PCTSTR host, PCTSTR port, int flags, int family, int sockType, int protocol)
    : head(NULL), next(NULL)
{
    ADDRINFOT hints = {0};
    hints.ai_flags      = flags;
    hints.ai_family     = family;
    hints.ai_socktype   = sockType;
    hints.ai_protocol   = protocol;
    hints.ai_next       = NULL;
    if (GetAddrInfo(host, port, &hints, &head) == 0) {
        assert(head != NULL);
        next = head;
    }
}

KHostAddress::~KHostAddress()
{
    if (head) {
        FreeAddrInfo(head);
    }
}

KIpAddress::KIpAddress(u_short port, KIpAddress::Special ip)
{
    switch (ip) {
    case KIpAddress::Broadcast:
        reset(htons(port), htonl(INADDR_BROADCAST));
        break;
    case KIpAddress::LocalHost:
        reset(htons(port), htonl(INADDR_LOOPBACK));
        break;
    default:
        reset(htons(port), htonl(INADDR_ANY));
        break;
    }
}

std::wstring KIpAddress::hostName() const
{
    WCHAR host[NI_MAXHOST];
    if (GetNameInfoW(name(), length(), host, NI_MAXHOST, NULL, 0, 0)) {
        KDebugLib("GetNameInfoW() failed: %d", WSAGetLastError());
        return std::wstring();
    }
    return host;
}

void KIpAddress::reset(u_short netPort, u_long netIp)
{
    reset();
    m_addrIn.sin_family = AF_INET;
    m_addrIn.sin_port = netPort;
    m_addrIn.sin_addr.s_addr = netIp;
}

void KIpAddress::reset(u_short port, const char *ip)
{
    reset(htons(port), (ip && *ip) ? inet_addr(ip) : htonl(INADDR_ANY));
}

void KIpAddress::reset(const KIAddress &host)
{
    if (host.isNull()) {
        reset();
    } else {
        reset(*reinterpret_cast<const SOCKADDR_IN *>(host.name()));
    }
}